<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>es5 new操作原型赋值</title>
  <!-- 
  在JavaScript中， `new` 操作符用于创建一个新对象并调用构造函数。使用 `new` 操作符时，原型赋值是实现对象继承和共享方法的重要机制。
  一、 `new` 操作符的基本用法
  使用 `new` 操作符时，会执行以下步骤：
  1. 创建一个新对象： `new` 操作符会创建一个空对象。
  2. 设置原型：新对象的 `__proto__` 属性指向构造函数的 `prototype` 属性。
  3. 绑定 `this` ：在构造函数内部， `this` 指向新创建的对象。
  4. 执行构造函数：调用构造函数，并传入参数。
  5. 返回对象：如果构造函数没有显式返回一个对象，则返回新创建的对象。

  二、原型赋值
  原型赋值是通过将构造函数的 `prototype` 属性赋值给新对象的 `__proto__` 来实现的。这样，新对象就可以访问构造函数原型上定义的方法和属性。
  function Person(name) {
      this.name = name; // 赋值给新对象的属性
  }

  // 在原型上定义一个方法
  Person.prototype.greet = function() {
      console.log('Hello, ' + this.name);
  };

  // 使用new操作符创建新对象
  var alice = new Person('Alice');
  alice.greet(); // 输出: Hello, Alice
  在这个例子中， `alice` 对象通过 `new Person('Alice')` 创建。 `alice` 的 `__proto__` 指向 `Person.prototype` ，因此可以访问 `greet` 方法。

  三、继承与原型赋值
  通过原型赋值，可以实现对象的继承。子构造函数可以通过 `Object.create()` 方法或直接赋值的方式来继承父构造函数的原型。
  function Animal(name) {
      this.name = name;
  }

  Animal.prototype.speak = function() {
      console.log(this.name + ' makes a noise.');
  };

  function Dog(name) {
      Animal.call(this, name); // 调用父构造函数，继承属性
  }

  // 继承父类的原型
  Dog.prototype = Object.create(Animal.prototype);
  Dog.prototype.constructor = Dog; // 修正构造函数指向

  Dog.prototype.speak = function() {
      console.log(this.name + ' barks.');
  };

  var dog = new Dog('Rex');
  dog.speak(); // 输出: Rex barks.
  在这个例子中， `Dog` 构造函数通过 `Object.create(Animal.prototype)` 继承了 `Animal` 的原型，这样 `Dog` 实例就可以访问 `Animal` 原型上的 `speak` 方法。

  四、总结
  -  `new` 操作符用于创建新对象，并自动设置原型。
  - 新对象的 `__proto__` 属性指向构造函数的 `prototype` ，从而实现方法的共享。
  - 通过原型赋值，可以实现对象的继承，使子对象能够访问父对象的属性和方法。
   -->
</head>
<body>

  <script>
    // 1. new 操作符
    function Foo() {
      // 1. 创建一个空对象
      // 2. 将空对象的 __proto__(隐式原型) 属性指向构造函数的 prototype 
      // 3. 将构造函数的 this 指向这个空对象
      // 4. 返回这个空对象
    }

    console.log(Foo.prototype);
    var f1 = new Foo()
    var f2 = new Foo()
    var f3 = new Foo()
    var f4 = new Foo()
    var f5 = createNew(Foo)
    console.log(f1.__proto__, f1, f5)
    console.log(f1.__proto__ === Foo.prototype) // true
    console.log(f3.__proto__ === f5.__proto__) // true

    function createNew(fn, ...args) {
      const obj = {}
      obj.__proto__ = fn.prototype
      const result = fn.apply(obj, args)
      return result instanceof Object ? result : obj
    }
    
  </script>
  
</body>
</html>